/*
 * Project: Made 2 Order Software utility package
 * Package: com.made2ordersoftware.util
 * File: LoginMgr
 * Creation Date: Sep 13, 2009
 */

/*
 *  Copyright (c) 2010 Made 2 Order Software, LLC
 *
 *  All rights reserved. No part of this software may be reproduced, stored in a retrieval system, or
 *  transmitted in any form or by any means, without the prior written permission of Made 2 Order Software.
 *
 *  You may not distribute the URL or redistribute the files to third parties. You may transfer the files
 *  onto a single storage device so long as you can prove ownership of the software. You may not reverse
 *  engineer, decompile, or disassemble the software or media files. You may not modify or translate the
 *  software or media, or distribute copies of the software or media without the written consent of Made
 *  2 Order Software
 */
package com.made2ordersoftware.util;

import com.made2ordersoftware.exceptions.InvalidFormatException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Class containing public static and helper methods for String pattern recognition and String manipulation.
 *
 * @author David Canning <dcannin@gmail.com>
 * @version 1.0.0
 */
public class StringUtility {

    private static final Logger LOG = LoggerFactory.getLogger(StringUtility.class);

    /**
     * Determines if String ssn matches pattern of a Social Security Number.
     *
     * @param ssn String being passed in for comparison.
     *
     * @return String with all non-digit characters removed.
     *
     * @throws InvalidFormatException Exception thrown if pattern does not match.
     */
    public static String validateSSN(String ssn) throws InvalidFormatException {
        LOG.info("Validating social security number");
        char[] a = {'-', ' '};
        String formattedSsn = removeChars(ssn, a);
        try {
            Double.parseDouble(formattedSsn);
        } catch (NumberFormatException e) {
            throw new InvalidFormatException("made2ordersoftware.util:" + "MyString:isValidSSN:" + e.
                    getClass() + ":" + "Improperly formatted phone number", e);
        }
        return formattedSsn;
    }

    /**
     * Determines if String zip matches pattern of a US zip/postal code. This method will return true for both
     * xxxxx and xxxxx-xxxx.
     *
     * @param zip String being passed in for comparison.
     *
     * @return String with all non-digit characters removed.
     *
     * @throws InvalidFormatException Exception thrown if pattern does not match.
     */
    public static String validateZipCode(String zip) throws InvalidFormatException {
        LOG.info("Validating zip code");
        char[] a = {'-', ' '};
        String formattedZip = removeChars(zip, a);
        try {
            Double.parseDouble(formattedZip);
        } catch (NumberFormatException e) {
            throw new InvalidFormatException("made2ordersoftware.util:" + "MyString:isValidZipCode:"
                    + e.
                    getClass() + ":" + "Improperly formatted zip code", e);
        }
        return formattedZip;
    }

    /**
     * Determines if String number matches pattern of 7 or 10 numeric digits. This method does not determine
     * if the original number matches a "real" US phone number.
     *
     * @param number String being passed in for comparison.
     *
     * @return String with all non-digit characters removed.
     *
     * @throws InvalidFormatException Exception thrown if pattern does not match.
     */
    public static String validatePhoneNumber(String number) throws InvalidFormatException {
        LOG.info("Validating phone number");
        char[] a = {'-', '+', '(', ')', ' '};
        String formattedNumber = removeChars(number, a);
        try {
            Double.parseDouble(formattedNumber);
        } catch (NumberFormatException e) {
            throw new InvalidFormatException("made2ordersoftware.util:"
                    + "MyString:isValidPhoneNumber:" + e.getClass() + ":"
                    + "Improperly formatted phone number", e);
        }
        return formattedNumber;
    }

    /**
     * Determines if String email matches pattern for most common email formats.
     *
     * @param email String being passed in for comparison.
     *
     * @throws InvalidFormatException Exception thrown if pattern does not match.
     */
    public static void validateEmail(String email) throws InvalidFormatException {
        LOG.info("Validating email address");
        Pattern p = Pattern.compile(".+@.+\\.[a-z]+");
        Matcher m = p.matcher(email.trim());
        if (!m.matches()) {
            throw new InvalidFormatException("made2ordersoftware.util:"
                    + "MyString:isValidEmail::Improperly formatted email address");
        }
    }

    /**
     * Private utility method to remove characters not needed for comparisons.
     *
     * @param s
     * @param a
     *
     * @return The original String s minus all characters in list a.
     */
    private static String removeChars(String s, char[] a) {
        StringBuilder r = new StringBuilder(10);
        for (int i = 0; i < s.length(); i++) {
            if (!contains(s.charAt(i), a)) {
                r.append(s.charAt(i));
            }
        }
        return r.toString();
    }

    /**
     * Private utility method to see if a character is in the list of unneeded characters.
     *
     * @param c The character used for comparison.
     * @param a The array of unneeded characters
     *
     * @return True if char c is in list a, false otherwise.
     */
    private static boolean contains(char c, char[] a) {
        for (int i = 0; i < a.length; i++) {
            if (c == a[i]) {
                return true;
            }
        }
        return false;
    }

    /**
     *
     * @param obj
     *
     * @return
     */
    public static String ifNotNullToString(Object obj) {
        if (obj == null) {
            return "";
        }
        if (obj instanceof Long) {
            return Long.toString((Long) obj);
        }
        if (obj instanceof Integer) {
            return Integer.toString((Integer) obj);
        }
        if (obj instanceof Float) {
            return Float.toString((Float) obj);
        }
        return null;
    }

}
